﻿// ===============================================================================
// RoutingDispatchModule.cs
// EOS Framework
// ===============================================================================
// Copyright (c) EOS Development Group. All rights reserved.
// ===============================================================================

namespace EOS.Framework.Web.Routing
{
    using System;
    using System.Security.Permissions;
    using System.Web;
    using EOS.Framework.Contracts.Web.Routing;
    using EOS.Framework.Kernel;

    /// <summary>
    /// Simple Http Module, which gets the current route from the router
    /// and invokes the specified handler of the matching route.
    /// </summary>
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    public class RoutingDispatchModule : IHttpModule
    {
        /// <summary>
        /// Name of the key, where we store our temporary data
        /// int the http item list.
        /// </summary>
        private const string RequestDataKey = "UrlRoutingData";

        #region IHttpModule Member

        /// <summary>
        /// Initializes a module and prepares it to handle requests.
        /// </summary>
        /// <param name="context">An <see cref="T:System.Web.HttpApplication"/> that 
        /// provides access to the methods, properties, and events common to all application 
        /// objects within an ASP.NET application</param>
        public void Init(HttpApplication context)
        {
            context.PostResolveRequestCache += new EventHandler(OnApplicationPostResolveRequestCache);
            context.PostMapRequestHandler += new EventHandler(OnApplicationPostMapRequestHandlerHandler); 
        }

        /// <summary>
        /// Called when ASP.NET bypasses execution of the current event 
        /// handler and allows a caching module to serve a request from the cache.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
        {
            HttpApplication application = sender as HttpApplication;
            
            MatchingRoute currentRoute = ServiceLocator.Current.GetInstance<IRouter>().FindBestRoute(
                application.Request.Url, application.Request.ApplicationPath);

            if (currentRoute != null)
            {
                IHttpHandler httpHandler = null;
                httpHandler = currentRoute.Handler.GetHttpHandler(currentRoute);

                if (httpHandler != null)
                {
                    RequestData data = new RequestData(httpHandler, application.Request.Path);
                    application.Context.Items[RequestDataKey] = data;
                    application.Context.RewritePath("~/UrlRouting.axd");
                }
                else
                {
                    throw new HttpException("There is not http handler for the current route.");
                }
            }
        }

        /// <summary>
        /// Called when when ASP.NET has mapped the current request to the 
        /// appropriate event handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance 
        /// containing the event data.</param>
        private void OnApplicationPostMapRequestHandlerHandler(object sender, EventArgs e)
        {
            HttpApplication application = sender as HttpApplication;
            RequestData data = (RequestData)application.Context.Items[RequestDataKey];
           
            if (data != null)
            {
                application.Context.RewritePath(data.Path);
                application.Context.Handler = data.HttpHandler;
            }
        }

        #endregion

        #region IDisposable Member

        /// <summary>
        /// Disposes of the resources (other than memory) used by the 
        /// module that implements <see cref="T:System.Web.IHttpModule"/>.
        /// </summary>
        public void Dispose()
        {
            /* Just do nothing */
        }

        #endregion
    }
}
